package net.qiqbframework.loadhanding;

import lombok.extern.slf4j.Slf4j;
import net.qiqbframework.eventsourcing.EventStorageEngine;
import net.qiqbframework.modelling.domain.AggregateModel;
import net.qiqbframework.modelling.domain.AnnotatedAggregate;
import net.qiqbframework.modelling.domain.FetchSource;
import net.qiqbframework.serialization.SerializedObject;
import net.qiqbframework.serialization.Serializer;

import java.util.concurrent.Callable;

@Slf4j
public class JdbcAggregate<AR> extends AnnotatedAggregate<AR> {

    private final Serializer aggregateRootSerializer;
    /**
     * 聚合根快照
     */

    private SerializedObject<byte[]> snapshotAggregateRoot;

    public AR getSnapshotAggregateRoot() {
        return aggregateRootSerializer.deserialize(snapshotAggregateRoot);
    }

    protected JdbcAggregate(AggregateModel<AR> model, EventStorageEngine eventStorageEngine, Serializer aggregateRootSerializer) {
        super(model, eventStorageEngine);
        this.aggregateRootSerializer = aggregateRootSerializer;
    }

    private void snapshotAggregateRoot() {
        try {
            this.snapshotAggregateRoot = aggregateRootSerializer.serialize(aggregateRoot, byte[].class);
        } catch (Exception e) {
            log.error("Aggregate  type[%s]  serialize error".formatted(aggregateModel.entityClass().getName()), e);
            throw e;
        }
    }

    public static <T> JdbcAggregate<T> initializeLoad(Callable<T> aggregateFactory, AggregateModel<T> aggregateModel, EventStorageEngine eventStorageEngine
            , Serializer aggregateRootSerializer) throws Exception {
        JdbcAggregate<T> aggregate = new JdbcAggregate<>(aggregateModel, eventStorageEngine, aggregateRootSerializer);
        aggregate.updateFetchSource(FetchSource.LOAD.getValue());
        aggregate.registerRoot(aggregateFactory);

        aggregate.snapshotAggregateRoot();
        return aggregate;
    }

    public static <T> JdbcAggregate<T> initializeCreate(Callable<T> aggregateFactory, AggregateModel<T> aggregateModel, EventStorageEngine eventStorageEngine
            , Serializer aggregateRootSerializer) throws Exception {
        JdbcAggregate<T> aggregate = new JdbcAggregate<>(aggregateModel, eventStorageEngine, aggregateRootSerializer);
        aggregate.updateFetchSource(FetchSource.CREATE.getValue());
        aggregate.registerRoot(aggregateFactory);
        aggregate.snapshotAggregateRoot();
        return aggregate;
    }


}
